package com.tensquare.article.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.tensquare.article.client.NoticeClient;
import com.tensquare.article.dao.ArticleDao;
import com.tensquare.article.pojo.Article;
import com.tensquare.notice.pojo.Notice;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import util.IdWorker;

import javax.swing.*;
import java.util.*;
import java.util.logging.Handler;

/**
 * @author wz
 * @company 公司
 * @create 2020-02-07 16:05
 */
@Service
public class ArticleService {
    @Autowired
    private ArticleDao articleDao;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private NoticeClient noticeClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public List<Article> findAll() {
        List<Article> articles = articleDao.selectList(null);
        return articles;
    }

    public Article findById(String id) {
        Article article = articleDao.selectById(id);
        return article;
    }

    public void save(Article article) {


        //TODO:使用 jwt鉴权获取用户的信息,用户id也就是文章作者id
        String userId = "3";
        article.setUserid(userId);
        //使用分布式id生成器
        String id = idWorker.nextId() + "";
        article.setId(id);

        //初始化数据
        article.setVisits(0); // 浏览量
        article.setThumbup(0); // 点赞数
        article.setComment(0);//评论数

        //新增
        articleDao.insert(article);

        //新增文章后 要发送消息给订阅者

        //获取订阅者信息
        //存放作者订阅者集合,里面存放订阅者id    作者的集合
        String authorKey = "article_author" + userId;
        Set<String> set = redisTemplate.boundSetOps(authorKey).members();


        //给订阅者创建消息通知
        for (String uid : set) {
            Notice notice = new Notice();
            notice.setReceiverId(uid);
            notice.setOperatorId(userId);
            notice.setAction("publish");
            notice.setTargetType("article");
            notice.setTargetId(id);
            notice.setType("sys");
//  `receiverId` varchar(20) DEFAULT NULL COMMENT '接收消息用户的ID',
//  `operatorId` varchar(20) DEFAULT NULL COMMENT '进行操作用户的ID',
//  `action` varchar(255) DEFAULT NULL COMMENT '操作类型（评论，点赞等）',
//  `targetType` varchar(255) DEFAULT NULL COMMENT '被操作的对象，例如文章，评论等',
//  `targetId` varchar(20) DEFAULT NULL COMMENT '被操作对象的id，例如文章的id，评论的id',
//  `createtime` datetime DEFAULT NULL COMMENT '发表日期',
//  `type` varchar(20) DEFAULT NULL COMMENT '通知类型',

            noticeClient.save(notice);
        }
        //发消息给RabbitMQ,就是新消息通知
        //第一个参数是交换机名称(订阅工功能交换价)  第二个参数是路由键(文章作者id) 第三个消息内容 只是新消息提醒,内容是文章id
        rabbitTemplate.convertAndSend("article_subscribe",userId,id);
    }

    public void update(Article article) {
        //根据主键id修改
        //articleDao.updateById(article);
        //根据条件修改
        //创建条件对象
        EntityWrapper<Article> wrapper = new EntityWrapper<>();
        //设置值
        wrapper.eq("id", article.getId());
        articleDao.update(article, wrapper);
    }

    public void delete(String id) {
        articleDao.deleteById(id);
    }

    public Page<Article> findBYPage(Map<String, Object> map, Integer page, Integer size) {
        //设置查询条件
        EntityWrapper<Article> wrapper = new EntityWrapper<>();
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
//            if (map.get(key)!=null){
//                wrapper.eq(key,map.get(key));
//            }
            //第一个参数是一个boolean值,来确定后面的条件是否加入到插叙中
            //和上面的条件是一样的
            wrapper.eq(map.get(key) != null, key, map.get(key));
        }
        //设置分页参数
        Page<Article> pageData = new Page<>(page, size);
        //执行查询
        List<Article> articles = articleDao.selectPage(pageData, wrapper);

        pageData.setRecords(articles);
        //返回
        return pageData;
    }

    public Boolean subscribe(String articleId, String userId) {
        //根据文章id查询作者id
        String authorId = articleDao.selectById(articleId).getUserid();

        //1.创建rabbit管理器
        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate.getConnectionFactory());
        //2.创建Direct交换机,处理新增文章消息
        DirectExchange  directExchange = new DirectExchange("article_subscribe");
        rabbitAdmin.declareExchange(directExchange);
        //3.声明队列,每个用户的都有自己的队列,采用用户id来区分
        Queue queue = new Queue("article_subscribe_"+userId,true);
        //4.声明交换机和队列的绑定关系,需要确保队列值收到对应作者新增文章的消息
        //1.队列  2.交换机  3.路由键就是作者id
        Binding binding = BindingBuilder.bind(queue).to(directExchange).with(authorId);
        //通过路由键进行绑定作者,队列只收绑定作者的文章消息.


        //存放用户订阅信息集合 ,里面存放作者id   用户的集合
        String userKey = "article_subscribe" + userId;
        //存放作者订阅者集合,里面存放订阅者id    作者的集合
        String authorKey = "article_author" + authorId;
        //查询用户订阅关系,是否订阅
        Boolean flag = redisTemplate.boundSetOps(userKey).isMember(authorId);
        if (flag) {
            //如果订阅就取消  返回false
            //分别删除用户集合中的作者id   作者集合中的用户id
            redisTemplate.boundSetOps(userKey).remove(authorId);
            redisTemplate.boundSetOps(authorKey).remove(userId);

            //如果取消订阅,就删除绑定关系
            rabbitAdmin.removeBinding(binding);
            return false;
        } else {
            //没有的话就订阅  true
            redisTemplate.boundSetOps(userKey).add(authorId);
            redisTemplate.boundSetOps(authorKey).add(userId);
            //声明要绑定的队列
            rabbitAdmin.declareQueue(queue);
            //如果订阅,就添加绑定关系
            rabbitAdmin.declareBinding(binding);
            return true;
        }
    }

    public void thumbup(String articleId) {

        Article article = articleDao.selectById(articleId);
        article.setThumbup(article.getThumbup() + 1);
        articleDao.updateById(article);

        //点赞成功后需要发送消息给文章作者(点对点消息)
        Notice notice = new Notice();
        notice.setReceiverId(article.getUserid());
        notice.setOperatorId("4");
        notice.setAction("thumbup");
        notice.setTargetType("article");
        notice.setTargetId(articleId);
        notice.setCreatetime(new Date());
        notice.setType("user");
        notice.setState("0");

        noticeClient.save(notice);

        //1.创建rabbit管理器
        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate.getConnectionFactory());
        //2.声明队列,每个用户的都有自己的队列,采用用户id来区分
        Queue queue = new Queue("article_thumbup_"+article.getUserid(),true);
        rabbitAdmin.declareQueue(queue);
        //3.发送消息
        rabbitTemplate.convertAndSend("article_thumbup_"+article.getUserid(),articleId);
    }

    public void dept() {
        /* @param dataBaseNameNew 另一个库名
         * @param databaseTableNameNew 另一个库的表名字
         * @param dataBaseNameOld 当前库名
         * @param databaseTableNameOld 当前库表名
         */
        String dataBaseNameNew ="tensquare_article";
        String databaseTableNameNew ="tb_article";
        String dataBaseNameOld ="tensquare_article";
        String databaseTableNameOld ="ceshi";

    }
}
